"""
Case Type   : mot
Case Name   : 打开enable_mot_server参数，备机重建，gs_ctl build指定参数-b full
Create At   : 2025/4/9
Owner       : @li-xin12345
Description : (编译带mot，不编译ENABLE_X86_RDTSCP，对应转测包)
    1、设置enable_incremental_checkpoint=off，enable_mot_server=on,
    most_available_sync=on
    2、建表
    3、停备机，主机继续插入数据
    4、备机重建,指定参数-b full
    5、清理环境
Expect      :
    1、成功
    2、成功
    3、成功
    4、成功
    5、成功
History     :
"""

import os
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger

primary_db_sh = CommonSH('PrimaryDbUser')
cluster_node_count = primary_db_sh.get_node_num()


@unittest.skipIf(3 > cluster_node_count, '不满足一主两备环境跳过')
class MotTest(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.std1_db_sh = CommonSH('Standby1DbUser')
        self.std2_db_sh = CommonSH('Standby2DbUser')
        self.pri_node_sh = Node('PrimaryDbUser')
        self.constant = Constant()
        self.common = Common()
        self.tb_name = 't_guc_mot_0033'
        self.view_name = 'v_guc_mot_0033'
        self.backup_dir = 'f_guc_mot_0033'
        self.index_name = 'i_guc_mot_0033'
        self.param_names = ['enable_incremental_checkpoint',
                            'enable_mot_server', 'most_available_sync']
        self.default_values = [self.common.show_param(i) for i in
                               self.param_names]
        self.log.info(self.default_values)
        self.backup_path = os.path.join(os.path.dirname(
            macro.DB_INSTANCE_PATH), self.backup_dir)

    def test_mot(self):
        text = '-----step1:设置enable_incremental_checkpoint=off，' \
               'enable_mot_server=on,most_available_sync=on;expect:成功-----'
        self.log.info(text)
        res = primary_db_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        f'{self.param_names[0]}=off')
        self.log.info(res)
        self.assertTrue(res, "执行gs_guc set失败，预期成功但未找到标志信息")
        res = primary_db_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        f'{self.param_names[1]}=on')
        self.log.info(res)
        self.assertTrue(res, "执行gs_guc set失败，预期成功但未找到标志信息")
        res = self.common.show_param(self.param_names[2])
        if res != 'on':
            res = primary_db_sh.execute_gsguc('set',
                                            self.constant.GSGUC_SUCCESS_MSG,
                                            f'{self.param_names[2]}=on')
            self.log.info(res)
            self.assertTrue(res, "执行gs_guc set失败，预期成功但未找到标志信息")
        res = primary_db_sh.restart_db_cluster()
        self.log.info(res)
        self.assertTrue(res, '执行失败：' + text)
        status = primary_db_sh.get_db_cluster_status()
        self.assertTrue("Normal" or "Degrade" in status)
        res = [self.common.show_param(i) for i in self.param_names]
        self.log.info(res)
        self.assertEqual(['off', 'on', 'on'], res, '执行失败：' + text)

        text = '-----step2:建表;expect:成功-----'
        self.log.info(text)
        sql = f'''drop foreign table if exists {self.tb_name} cascade;
        create foreign table {self.tb_name} (id int primary key, 
        name varchar(100) not null, age int not null default 0);
        create index {self.index_name} on {self.tb_name} (name);
        insert into {self.tb_name} (id, name, age) values (1, 'alice', 25), 
        (2, 'bob', 30),(3, 'charlie', 35);
        select * from {self.tb_name} where age > 30;
        update {self.tb_name} set age = 26 where id = 1;
        begin;
        insert into {self.tb_name} (id, name, age) values (4, 'david', 40);
        commit;
        create or replace view {self.view_name} as
        select id, name, age from {self.tb_name} where age > 30;
        select * from {self.view_name};
        '''
        sql_res = primary_db_sh.execut_db_sql(sql)
        self.log.info(sql_res)
        self.assertIn(self.constant.DROP_FOREIGN_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.CREATE_FOREIGN_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.CREATE_INDEX_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.INSERT_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.COMMIT_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.CREATE_VIEW_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn('2 rows', sql_res, '执行失败：' + text)

        text = '-----step3:停备机，主机继续插入数据;expect:成功-----'
        self.log.info(text)
        self.std1_db_sh.stop_db_instance()
        self.std2_db_sh.stop_db_instance()
        self.log.info('---查看备机状态---')
        status = primary_db_sh.get_db_cluster_status('detail')
        self.log.info(status)
        self.assertIn('Degrade', status, '执行失败：' + text)

        sql = (f"insert into {self.tb_name} (id, name, age) values "
               f"(generate_series(1000, 100000), 'david', 50);")
        sql_res = primary_db_sh.execut_db_sql(sql)
        self.log.info(sql_res)
        self.assertIn('INSERT 0 99001', sql_res, '执行失败：' + text)

        text = '-----step4:备机重建,指定参数-b full;expect:成功-----'
        self.log.info(text)
        build_res1 = self.std1_db_sh.build_standby()
        self.assertIn(self.constant.BUILD_SUCCESS_MSG, build_res1)
        build_res2 = self.std2_db_sh.build_standby()
        self.assertIn(self.constant.BUILD_SUCCESS_MSG, build_res2)

    def tearDown(self):
        text = '-----step5:清理环境; expect:成功-----'
        self.log.info(text)
        status = primary_db_sh.get_db_cluster_status(param='status')
        self.log.info(status)
        if status is False:
            build_res1 = self.std1_db_sh.build_standby()
            self.assertIn(self.constant.BUILD_SUCCESS_MSG, build_res1)
            build_res2 = self.std2_db_sh.build_standby()
            self.assertIn(self.constant.BUILD_SUCCESS_MSG, build_res2)
            status = primary_db_sh.get_db_cluster_status(param='status')
            self.log.info(status)

        sql = f'drop foreign table if exists {self.tb_name} cascade;checkpoint;'
        drop_res = primary_db_sh.execut_db_sql(sql)
        self.log.info(drop_res)
        status = primary_db_sh.get_db_cluster_status(param='status')
        self.log.info(status)
        if status is True:
            self.log.info('--等待集群数据同步--')
            flag = primary_db_sh.check_data_consistency()
            self.assertTrue(flag, '执行失败：' + text)

        res = [self.common.show_param(i) for i in self.param_names]
        self.log.info(res)
        if res != self.default_values:
            for i, param_name in enumerate(self.param_names):
                res = primary_db_sh.execute_gsguc(
                    'set', self.constant.GSGUC_SUCCESS_MSG,
                    f'{param_name}={self.default_values[i]}')
                self.log.info(res)
            restart_res = primary_db_sh.restart_db_cluster()
            self.log.info(restart_res)
            status = primary_db_sh.get_db_cluster_status()
            self.log.info(status)
            show_param = [self.common.show_param(i) for i in self.param_names]
            self.log.info(show_param)
            self.assertEqual(self.default_values, show_param,
                             '执行失败：' + text)
            self.assertTrue(restart_res, '执行失败：' + text)

        self.assertIn(self.constant.DROP_FOREIGN_SUCCESS_MSG, drop_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.CHECKPOINT_SUCCESS_MSG, drop_res,
                      '执行失败：' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')